package com.gec.system.aop;

import cn.hutool.json.JSONUtil;
import com.gec.model.system.SysOperLog;
import com.gec.model.system.SysUser;
import com.gec.system.common.Result;
import com.gec.system.service.SysOperLogService;
import com.gec.system.service.SysUserService;


import com.gec.system.util.IpUtil;
import com.gec.system.util.JwtHelper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;


/**
 * @author:啊薰
 * @create:2024-05-30 22:22
 */
@Aspect
@Component
public class SystemLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    @Autowired
    private SysOperLogService sysOperLogService;

    @Autowired
    private SysUserService sysUserService;


    /**
     * Controller层切点
     */
    @Pointcut("within(com.gec.system.controller..*) && @annotation(SystemControllerLog)")
    //@Pointcut("@annotation(com.gec.system.controller.*.*.*.*.SystemControllerLog)")
    public void SystemControllerLog(){

    }


    /**
     * 前置通知 用于拦截Controller层记录用户的操作的开始时间
     * @param joinPoint 切点
     * @throws InterruptedException
     */
//    @Before("SystemControllerLog()")
//    public void doBefore(JoinPoint joinPoint) throws InterruptedException{
//        logger.info("进入日志切面前置通知!");
//       //得到request
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        //得到token
//        String token = request.getHeader("token");
//        String useruame = JwtHelper.getUsername(token);
//        user = sysUserService.getUserInfoUserName(useruame);
//        logger.info("得到用户信息："+user.toString());
//
//    }

    /**value切入点位置
     * returning 自定义的变量，标识目标方法的返回值,自定义变量名必须和通知方法的形参一样
     * 特点：在目标方法之后执行的,能够获取到目标方法的返回值，可以根据这个返回值做不同的处理
     */

    /**
     * 后置增强
     */
//    @AfterReturning(value = "SystemControllerLog()",returning = "systemControllerLog")
//    public void afterReturning(JoinPoint joinPoint,SystemControllerLog systemControllerLog)throws Throwable  {
////        String methodName = jp.getSignature().getName();
////        Object[] args = jp.getArgs();
////        Object target = jp.getTarget();  //衩拦截方法的目标对象（业务对象）
////        System.out.println("后置增强： 方法名：" + methodName + ", 参数列表：" + Arrays.toString(args)+", 目标对象：" + target+", 返回值 ：" + returnValue);
//        logger.info("设置日志信息存储到表中!");
//        //joinPoint.proceed() 结果集
//        //参数数组
//        Object[] args = joinPoint.getArgs();
//        //请求参数数据
//        String requestJson = JSONUtil.toJsonStr(args);
//        System.out.println("requestJson = " + requestJson);
//        //方法名
//        String methodName = joinPoint.getSignature().getName();
//
//
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
////        //写入数据库操作日志
//        SysOperLog sysOperLog = new SysOperLog();
//        sysOperLog.setOperName(user.getUsername());//用户名
//        sysOperLog.setTitle(systemControllerLog.module());//title xx管理
//        sysOperLog.setMethod(joinPoint.getSignature().getDeclaringTypeName()+"."+methodName+"()");//methon
//        sysOperLog.setOperatorType("MANAGE");//用户类型 默认的
//        sysOperLog.setBusinessType(systemControllerLog.operate());//类型
//        sysOperLog.setJsonResult(JSONUtil.toJsonStr(systemControllerLog));//响应返回值
//        sysOperLog.setCreateTime(new Date());
//        sysOperLog.setOperUrl(request.getRequestURI());
//        sysOperLog.setRequestMethod(request.getMethod());
//        sysOperLog.setOperParam(requestJson);
//        sysOperLog.setStatus(1);
//        sysOperLog.setOperIp(IpUtil.getIpAddress(request));
//        sysOperLog.setOperParam(requestJson);
//
//        System.out.println("sysOperLog = " + sysOperLog.toString());

////        //保存
       // sysOperLogService.save(sysOperLog);
//


  //  }

    /**
     * 通知包裹了目标方法，在目标方法调用之前和之后执行自定义的行为
     * ProceedingJoinPoint切入点可以获取切入点方法上的名字、参数、注解和对象
     * @param joinPoint
     */
    @Around("SystemControllerLog() && @annotation(systemControllerLog)")
    public Result doAfterReturning(ProceedingJoinPoint joinPoint,
                                   SystemControllerLog systemControllerLog) throws Throwable {

        logger.info("进入日志切面前置通知!");
//       //得到request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //得到token
        String token = request.getHeader("token");
        String useruame = JwtHelper.getUsername(token);
        SysUser user = sysUserService.getUserInfoUserName(useruame);
        logger.info("得到用户信息："+user.toString());
        logger.info("```````````````````````````````````````````````````````````````````````````````");
        logger.info("设置日志信息存储到表中!");
        //joinPoint.proceed() 结果集
        //参数数组
        Object[] args = joinPoint.getArgs();
        //请求参数数据
        String requestJson = JSONUtil.toJsonStr(args);
        System.out.println("requestJson = " + requestJson);
        //方法名
        String methodName = joinPoint.getSignature().getName();

        Result proceed = (Result) joinPoint.proceed();
//        //写入数据库操作日志
       SysOperLog sysOperLog = new SysOperLog();
        sysOperLog.setOperName(user.getUsername());//用户名
        sysOperLog.setTitle(systemControllerLog.module());//title xx管理
        sysOperLog.setMethod(joinPoint.getSignature().getDeclaringTypeName()+"."+methodName+"()");//methon
        sysOperLog.setOperatorType("MANAGE");//用户类型 默认的
        sysOperLog.setBusinessType(systemControllerLog.operate());//类型
        sysOperLog.setJsonResult(JSONUtil.toJsonStr(proceed));//响应返回值
        sysOperLog.setCreateTime(new Date());
        sysOperLog.setOperUrl(request.getRequestURI());
        sysOperLog.setRequestMethod(request.getMethod());
        sysOperLog.setOperParam(requestJson);
        sysOperLog.setStatus(1);
        sysOperLog.setOperIp(IpUtil.getIpAddress(request));
        sysOperLog.setOperParam(requestJson);
        //存入返回的结果集 joinPoint.proceed()
        System.out.println("sysOperLog = " + sysOperLog.toString());
        System.out.println("proceed = " + proceed);
////        //保存
        sysOperLogService.save(sysOperLog);

        return proceed;

    }
}
